﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;

namespace LEE.Tools.Others
{
    public class ReflectionHelper
    {
        /// <summary>
        /// 获取程序集中的实现类对应的多个接口
        /// </summary>
        /// <param name="assemblyName">程序集</param>
        public static Dictionary<Type, Type[]> GetClassName(string assemblyName)
        {
            if (string.IsNullOrEmpty(assemblyName)) return new Dictionary<Type, Type[]>();

            var assembly = Assembly.Load(assemblyName);
            var ts = assembly.GetTypes().ToList();

            var result = new Dictionary<Type, Type[]>();
            foreach (var item in ts.Where(s => !s.IsInterface))
            {
                var interfaceType = item.GetInterfaces();
                result.Add(item, interfaceType);
            }
            return result;
        }

        /// <summary>
        /// 获取某个类的所有子类
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <param name="topClass"></param>
        /// <returns></returns>
        public static List<Type> GetSubTypes(string assemblyName, string topClass)
        {
            if (string.IsNullOrEmpty(assemblyName)) return new List<Type>();

            var assembly = Assembly.Load(assemblyName);
            var type = assembly.GetType(topClass);
            var ts = assembly.GetTypes();
            var result = ts.Where(t => t.IsSubclassOf(type));
            return result.ToList();
        }

        /// <summary>
        /// 获取命名空间中的所有类
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <param name="namespaceName"></param>
        /// <returns></returns>
        public static List<Type> GetAllSpaceTypes(string assemblyName, string namespaceName)
        {
            var assembly = Assembly.Load(assemblyName);
            var ts = assembly.GetTypes();
            return ts.Where(t => t.Namespace == namespaceName).ToList();
        }

        /// <summary>
        /// 递归获取最终类
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <param name="topClass"></param>
        /// <returns></returns>
        public static List<Type> GetFinalTypes(string assemblyName, string topClass)
        {
            var result = new List<Type>();
            var assembly = Assembly.Load(assemblyName);
            var ts = assembly.GetTypes();
            foreach (var t in ts)
            {
                if (GetSubTypes(assemblyName, t.FullName).Count == 0)
                    result.Add(t);
                else
                    result.AddRange(GetFinalTypes(assemblyName, t.FullName));
            }
            return result;
        }



        /// <summary>
        /// 获取实体集合指定列名的字典集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="elements">实体集合</param>
        /// <param name="properties">指定列名集合(区分大小写)</param>
        /// <returns></returns>
        public static IEnumerable<Dictionary<string, string>> GetCustomProperties<T>(IEnumerable<T> elements, string[] properties) where T : class
        {
            var dics = new List<Dictionary<string, string>>();
            if (elements == null || !elements.Any())
            {
                var dic = properties.ToDictionary(key => key, value => "");
                dics.Add(dic);
            }
            else
            {
                foreach (var element in elements)
                {
                    var o = new Dictionary<string, string>();
                    var currentProperties = element.GetType().GetProperties();
                    foreach (var currentProperty in currentProperties)
                    {
                        if (properties.Any(i => i.Equals(currentProperty.Name, StringComparison.CurrentCultureIgnoreCase)))
                        {
                            string columnName = currentProperty.Name;
                            var attribute = currentProperty.GetCustomAttribute<DisplayNameAttribute>();
                            if (attribute != null) columnName = attribute.DisplayName;
                            var proValue = currentProperty.GetValue(element);
                            o[columnName] = proValue?.ToString();
                        }
                    }
                    dics.Add(o);
                }
            }
            return dics;
        }

        /// <summary>
        /// 获取实体类字段名称和显示名称集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetDisplayName(Type obj)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            var properties = obj.GetProperties();
            foreach (var property in properties)
            {
                var attribute = property.GetCustomAttribute<DisplayNameAttribute>();
                if (attribute != null)
                {
                    dic.Add(property.Name, attribute.DisplayName);
                }
                else
                {
                    dic.Add(property.Name, property.Name);
                }
            }
            return dic;
        }
    }
}


